from typing import Any

from aiogram import Bot, F, types
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import Back, Cancel, ScrollingGroup, Select, Start
from aiogram_dialog.widgets.text import Format
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from sqlalchemy.ext.asyncio import AsyncSession

from app.bot.dialog.dialog_states import (
    BuyProxySubscriptionSG,
    ManageProxySubscriptionSG,
    OrderDetailsSG,
    ProxySubscriptionSG,
)
from app.bot.dialog.getters.countries import countries_getter
from app.bot.dialog.getters.providers import providers_getter
from app.bot.dialog.widgets import LocaleText
from app.bot.services.locale import Locale
from app.bot.services.loggers import logger
from app.bot.services.scheduler import jobs
from app.config import Settings
from app.database.services.categories import get_category_by_name
from app.database.services.orders.subscriptions import get_user_subscription_order
from app.database.services.proxy import get_available_proxies


async def set_country_id(
    call: types.CallbackQuery, widget: Any, manager: DialogManager, country_id: str
):

    manager.dialog_data["country_id"] = country_id
    await manager.switch_to(ManageProxySubscriptionSG.select_provider)


async def set_proxy_provider(
    call: types.CallbackQuery, widget: Any, manager: DialogManager, provider_id: str
):
    session_factory = manager.middleware_data.get("session_factory")
    db_session: AsyncSession = manager.middleware_data.get("db_session")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")
    scheduler: AsyncIOScheduler = manager.middleware_data.get("scheduler")
    locale: Locale = manager.middleware_data.get("locale")
    country_id: int = manager.dialog_data.get("country_id")
    user_id: int = manager.middleware_data.get("event_from_user").id

    category = await get_category_by_name(db_session, "Подписка")
    subscription_order = await get_user_subscription_order(db_session, user_id)
    manager.dialog_data["order_id"] = subscription_order.id

    proxies = await get_available_proxies(
        db_session,
        proxy_type="mobile",
        proxy_privacy="private",
        country_id=country_id,
        provider_id=int(provider_id),
        category=category,
        limit=1,
    )

    if len(proxies) <= 0:
        await call.message.answer(locale.get("no-subscription-proxies"))
        return

    if len(subscription_order.proxies) > 0:
        proxy_id = subscription_order.proxies[0].id
    else:
        proxy_id = None

    new_proxy_id = proxies[0].id

    try:
        scheduler.add_job(
            jobs.change_proxy,
            args=(
                bot,
                locale,
                session_factory,
                user_id,
                subscription_order.id,
                proxy_id,
                new_proxy_id,
                config,
                country_id,
                provider_id,
            ),
        )

        logger.info(
            f"Добавлена задача по смене прокси в заказе №{subscription_order.id}"
        )

        scheduler.add_job(
            jobs.check_proxy_speed_job,
            args=(
                bot,
                locale,
                session_factory,
                user_id,
                new_proxy_id,
                config,
            ),
        )
        logger.info(f"Добавлена задача по проверке скорости прокси №{new_proxy_id}")

        await call.message.answer(locale.get("in-work-msg"))
    except Exception as e:
        logger.exception(e)
        await call.message.answer(locale.get("error-msg"))
    await manager.done()


async def get_user_subscription_status(
    db_session: AsyncSession, dialog_manager: DialogManager, **kwargs
):
    user_id: int = dialog_manager.middleware_data.get("event_from_user").id
    subscription_order = await get_user_subscription_order(db_session, user_id)
    if subscription_order:
        dialog_manager.dialog_data["order_id"] = subscription_order.id

    return {
        "subscription_order": subscription_order,
    }


subscription_info_window = Window(
    LocaleText("subscription-info"),
    Start(
        LocaleText("buy-subscription-btn"),
        id="buy_proxy_subscription",
        state=BuyProxySubscriptionSG.select_plan,
        when=~F["subscription_order"],
    ),
    Start(
        LocaleText("change-country-btn"),
        id="select_country_subscription",
        state=ManageProxySubscriptionSG.select_country,
        when=F["subscription_order"],
    ),
    Start(
        LocaleText("manage-subscription-btn"),
        id="manage_subscription_order",
        state=OrderDetailsSG.order_details,
        when=F["subscription_order"],
    ),
    Cancel(LocaleText("back-btn")),
    getter=get_user_subscription_status,
    state=ProxySubscriptionSG.show_info,
)

countries_window = Window(
    LocaleText("select-country"),
    ScrollingGroup(
        Select(
            Format("{item.name}"),
            "catselsel",
            lambda country: country.id,
            "countries",
            on_click=set_country_id,
        ),
        width=2,
        height=4,
        id="catsel",
        when=F["user_language"] == "ru",
    ),
    ScrollingGroup(
        Select(
            Format("{item.name_eng}"),
            "catselsel",
            lambda country: country.id,
            "countries",
            on_click=set_country_id,
        ),
        width=2,
        height=4,
        id="catsel",
        when=F["user_language"] == "en",
    ),
    Cancel(LocaleText("back-btn")),
    state=ManageProxySubscriptionSG.select_country,
    getter=countries_getter,
)


providers_window = Window(
    LocaleText("select-proxy-provider"),
    ScrollingGroup(
        Select(
            Format("{item.name}"),
            "catselsel",
            lambda provider: provider.id,
            "providers",
            on_click=set_proxy_provider,
        ),
        width=2,
        height=4,
        id="catsel",
        when=F["user_language"] == "ru",
    ),
    ScrollingGroup(
        Select(
            Format("{item.name_eng}"),
            "catselsel",
            lambda provider: provider.id,
            "providers",
            on_click=set_proxy_provider,
        ),
        width=2,
        height=4,
        id="catsel",
        when=F["user_language"] == "en",
    ),
    Back(LocaleText("back-btn")),
    Cancel(LocaleText("cancel-btn")),
    state=ManageProxySubscriptionSG.select_provider,
    getter=providers_getter,
)


subscription_info_dialog = Dialog(subscription_info_window)

manage_subscription_dialog = Dialog(countries_window, providers_window)
